/**
 * This class provides statical and popup menu funcitonality.
 *
 * @author Andrey Anisimov <hercules@inbox.ru>
 */

import core.ui.Window;
import core.util.Listeners;

class Menu extends Window {
	
	/**
	 * Creates new menu control.
	 * 
	 * @param parent (Window) [optional] parent window
	 * @param x, y (int) [optional] coordinates
	 * @param width, height (int) [optional] control size.
	 */	
	this.Menu = function(parent, x, y, width, height) {
		super(parent, x, y, width, height);
		this.setStyle('overflow', 'visible');
		this.items = [];
		this.popupinfo = {};
		this.listeners = new Listeners(['onEndPopup', 'onItemSelected']);
	}

	this.addMenuListener = function(listener) {
		this.listeners.add(listener);
	}

	this.removeMenuListener = function(listener) {
		this.listeners.remove(listener);
	}

	/**
	 * Shows menu in popup state.
	 *
	 * Note:
	 * If you secify origin window for this menu,
	 * when the user clicks to this window or any child of this window,
	 * the menu will continue popup. But when the user clicks on the other area,
	 * the popup state will be finished.
	 * 
	 * @param origin (Window) [optional] origin window for this menu.
	 * @param x, y (int) [optional] menu coordinates.
	 */
	this.doPopup = function(origin, x, y) {
		this.origin = origin;
		if (x && y) {
			this.move(x, y);
		}
		this.attachGlobalEvent('mousedown');
		this.attachGlobalEvent('keydown');
		this.popupinfo.popupState = true;
		this.activate();
		this.show();
	}

	/**
	 * Finishes popup state.
	 */
	this.endPopup = function() {
		if (this.popupinfo.popupState) {
			delete this.origin;
			this.popupinfo.popupState = false;
			this.detachGlobalEvent('mousedown');
			this.detachGlobalEvent('keydown');
			this.fireEndPopup();
			this.hide();
		}
	}

	this.fireEndPopup = function() {
		this.listeners.call('onEndPopup', [this]);
	}

	/**
	 * Checks whether the menu is in popup state.
	 *
	 * @param origin (Window) [optional] origin window to compare with.
	 * @return bool
	 */
	this.isPopup = function(origin) {
		if (this.popupinfo.popupState) {
			if (origin) {
				return (this.origin == origin);
			}
			return true;
		}
		return false;
	}
	
	/**
	 * Returns origin window for this popup menu.
	 *
	 * @return Window
	 */
	this.getOrigin = function() {
		return this.origin;
	}
	
	/**
	 * Addss new menu item.
	 * 
	 * @param item (Window) new menu item
	 */
	this.addItem = function(item) {
		this.items.push(item);
		return item;
	}
	
	/**
	 * Returns item by index.
	 * 
	 * @param index (int) item index
	 * @return Window
	 */
	this.getItem = function(i) {
		return this.items[i];
	}
	
	/**
	 * Returns menu item count.
	 *
	 * @return int
	 */
	this.getItemCount = function() {
		return this.items.length;
	}
	
	/**
	 * Removes item with specified index.
	 * 
	 * @param index (int) item index
	 */
	this.removeItem = function(i) {
		this.items[i].close();
		delete this.items[i];
		this.items.splice(i, 1);
	}
	
	/**
	 * Removes all menu items.
	 */
	this.removeItems = function() {
		while (this.items.length > 0) {
			var item = this.items.pop();
			item.close();
			delete item;
		}
	}
	
	/**
	 * Checks if the item with specified index is visible.
	 * If not, then scrolls to item.
	 * 
	 * @param i (int) item index
	 * @return bool
	 */
	this.ensureVisible = function(i) {
		this.getElement().scrollTop = this.items[i].getY();
	}
	
	this.onmousedown = function(event, target) {
		if (target instanceof Window) {
			if ((target == this) || target.isChildOf(this) || this.isChildOf(target)) {
				return;
			}
			if ((this.origin instanceof Window) && ((target == this.origin) || target.isChildOf(this.origin))) {
				return;
			}
			while (target.isChild()) {
				target = target.getParent();
			}
			if ((target instanceof Menu) && target.isPopup()) {
				return;
			}
		}
		this.endPopup();
	}
	
	this.onkeydown = function(event) {
		if (Event.KEY_ESCAPE == event.keyCode) {
			this.endPopup();
		}
	}

    /**
	 * @protected
	 */
	this.fireItemSelected = function() {
		this.listeners.call('onItemSelected', [this]);
	}
}